package com.ehotting.mqbd.api.bean.solver;

import com.ehotting.eaf.core.DateHelper;
import com.ehotting.mqbd.api.enums.ServerAvailableStateEnum;
import com.ehotting.mqbd.api.enums.ServerWorkStateEnum;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

@Slf4j
public class SolverStateBean implements java.io.Serializable{

    private String module;
    private SolverInfoBean solverInfo;
    private ServerAvailableStateEnum availableState = ServerAvailableStateEnum.NOT;
    private ServerWorkStateEnum workingState = ServerWorkStateEnum.FREE;
    private Long requestCount = 0L;
    private Long queueSize = 0L;
    private Date workTime;
    private Date availableTime;
    private Integer errorTimes = 0;
    private Integer solvingCount = 0;
    private Integer solveTotal = 1;
    private Date lastActiveTime = new Date();

    public SolverStateBean() {
    }

    public SolverStateBean(String module,SolverInfoBean solverInfo) {
        this.module = module;
        this.solverInfo = solverInfo;
    }

    public SolverInfoBean getSolverInfo() {
        return solverInfo;
    }

    public void setSolverInfo(SolverInfoBean solverInfo) {
        this.solverInfo = solverInfo;
    }

    public ServerAvailableStateEnum getAvailableState() {
        return availableState;
    }



    public void setAvailableState(ServerAvailableStateEnum availableState) {
        this.availableState = availableState;
    }

    public ServerWorkStateEnum getWorkingState() {
        return workingState;
    }

    public void setWorkingState(ServerWorkStateEnum workingState) {
        this.workingState = workingState;
    }

    public void addRequestCount(){
        requestCount++;
        if(requestCount >255){
            requestCount = 0L;
        }
    }

    public Long getRequestCount() {
        return requestCount;
    }

    public void setRequestCount(Long requestCount) {
        this.requestCount = requestCount;
    }

    private SolverStateBean setBusy(){
        workTime = new Date();
        this.setWorkingState(ServerWorkStateEnum.BUSY);
        return this;
    }
    private SolverStateBean setFree(){
        workTime = new Date();
        this.setWorkingState(ServerWorkStateEnum.FREE);
        return this;
    }

    private SolverStateBean setSolving(){
        workTime = new Date();
        this.setWorkingState(ServerWorkStateEnum.SOLVING);
        return this;
    }


    public SolverStateBean setAvailable(){
        availableTime = new Date();
        this.setAvailableState(ServerAvailableStateEnum.YES);
        this.setErrorTimes(0);
        return this;
    }

    public boolean isAvailable(){
        return availableState == ServerAvailableStateEnum.YES;
    }



    public SolverStateBean setStop(){
        availableTime = new Date();
        this.setAvailableState(ServerAvailableStateEnum.NOT);
        return this;
    }

    public Long getQueueSize() {
        return queueSize;
    }

    public void setQueueSize(Long queueSize) {
        this.queueSize = queueSize;
    }

    public Date getWorkTime() {
        return workTime;
    }

    public Date getAvailableTime() {
        return availableTime;
    }

    public void setWorkTime(Date workTime) {
        this.workTime = workTime;
    }

    public void setAvailableTime(Date availableTime) {
        this.availableTime = availableTime;
    }

    public Integer getErrorTimes() {
        return errorTimes;
    }
    public void setErrorTimes(Integer errorTimes) {
        this.errorTimes = errorTimes;
    }

    public void addErrorTimes(ModuleInfoBean moduleInfo) {
        Integer maxErrorTimes = (moduleInfo.getErrorTimes()==null)?5:moduleInfo.getErrorTimes();
        this.errorTimes ++;
        if(errorTimes >= maxErrorTimes){
            this.setStop();
        }

        if(this.isAvailable() == false){
            /**求解节点服务停止后，每60秒请求一次**/
            this.setLastActiveTime(DateHelper.minusSecond(new Date(), moduleInfo.getIntervalTime()-30));
        }else {
            /**求解节点服务停止后，每10秒请求一次**/
            this.setLastActiveTime(DateHelper.minusSecond(new Date(), moduleInfo.getIntervalTime()-10));
        }
    }

    public Integer getSolvingCount() {
        return solvingCount;
    }

    public void setSolvingCount(Integer solvingCount) {
        if(solvingCount > solveTotal){
            log.error("Module[{}] setSolvingCount(solvingCount[{}] > solveTotal[{}]),error.",module,solvingCount,solveTotal);
        }
        if(solvingCount<0){
            log.error("Module[{}] setSolvingCount(solvingCount[{}] < 0),error.",module,solvingCount);
        }
        this.solvingCount = solvingCount;
        handleSolvingCount();
    }

    public void addSolvingCount() {
        if(solvingCount < solveTotal) {
            solvingCount++;
        }else {
            log.error("Module[{}] addSolvingCount(solvingCount[{}] == solveTotal[{}]),error.",module,solvingCount,solveTotal);
        }
        handleSolvingCount();
    }

    public void minusSolvingCount() {
        if(solvingCount>0) {
            solvingCount--;
        }else {
            log.error("Module[{}] minusSolvingCount(solvingCount[{}]),error.",module,solvingCount);
        }
        handleSolvingCount();
    }

    public Integer getSolveTotal() {
        return solveTotal;
    }

    public void setSolveTotal(Integer solveTotal) {
        this.solveTotal = solveTotal;
    }

    private void handleSolvingCount(){
        if(solvingCount.equals(0)){
            this.setFree();
        }
        if(solvingCount>0 && solvingCount<solveTotal){
            this.setSolving();
        }
        if(solvingCount>=solveTotal){
            this.setBusy();
        }
    }

    public String getModule() {
        return module;
    }

    public void setModule(String module) {
        this.module = module;
    }

    public Date getLastActiveTime() {
        return lastActiveTime;
    }

    public void setLastActiveTime(Date lastActiveTime) {
        this.lastActiveTime = lastActiveTime;
    }
}
